import pandas
import hashlib
import getpass
import os
import matplotlib.pyplot as plt
from cryptography.fernet import Fernet
import sys


plt.rcParams["font.sans-serif"] = ["Arial Unicode MS", "simhei"]


class RwCsv:
    def __init__(self):
        self.back_help = []
        self.now_score = 0
        self.choose = []

    def init(self):
        for i in range(8):
            df = pandas.read_csv(f"data/group{i+1}.csv")
            df["score"] = df["score"].astype("float64")
            a = len(df["score"])
            for j in range(a):
                df.iloc[j, 2] = 0
            df.to_csv(f"data/group{i+1}.csv", index=False)

    def change(self, message):
        """加减分"""
        try:
            message = float(message)
        except ValueError:
            """2.一个字符串"""
            self._update_score(message)
        else:
            """3.一个数字"""
            self.now_score = message
            print(f"已改为{self.now_score}分")

    def _update_score(self, name):
        for i in range(8):
            df = pandas.read_csv(f"data/group{i+1}.csv")
            df["score"] = df["score"].astype("float64")
            dfd = df.values
            for j in range(len(dfd)):
                c = dfd[j]
                if c[1] == name:
                    self.choose.append([c[0], i + 1, j])
        if len(self.choose) == 0:
            print("用户不存在")
            return
        elif len(self.choose) == 1:
            df = pandas.read_csv(f"data/group{self.choose[0][1]}.csv")
            df["score"] = df["score"].astype("float64")
            df.iloc[self.choose[0][2], 2] += self.now_score
            df.to_csv(f"data/group{self.choose[0][1]}.csv", index=False)
            print(f"{self.choose[0][0]}已加{self.now_score}分")
        else:
            for index, nm in enumerate(self.choose):
                print(index, nm[0])
            cnum = int(input("输入加分人的序号:"))
            df = pandas.read_csv(f"data/group{self.choose[cnum][1]}.csv")
            df["score"] = df["score"].astype("float64")
            df.iloc[self.choose[cnum][2], 2] += self.now_score
            df.to_csv(f"data/group{self.choose[cnum][1]}.csv", index=False)
            print(f"{self.choose[cnum][0]}已加{self.now_score}分")
        self.choose.clear()


class Crypto:
    def create_key_file(self):
        key = Fernet.generate_key()
        with open("crypto/key.key", "wb") as f:
            f.write(key)

    def load_key_file(self):
        with open("crypto/key.key", "rb") as f:
            key = f.read()
        return key

    def encrypt(self):
        cipher = Fernet(self.load_key_file())
        for i in range(8):
            with open(f"data/group{i+1}.csv", "rb") as f:
                data = f.read()
            encrypted = cipher.encrypt(data)
            with open(f"data/group{i+1}.csv", "wb") as f:
                f.write(encrypted)

    def decrypt(self):
        cipher = Fernet(self.load_key_file())
        for i in range(8):
            with open(f"data/group{i+1}.csv", "rb") as f:
                data = f.read()
            decrypted = cipher.decrypt(data)
            with open(f"data/group{i+1}.csv", "wb") as f:
                f.write(decrypted)


class Visual:
    def __init__(self):
        self.crypto = Crypto()
        self.reader = RwCsv()

    def _visual_sum_pre_do(self):
        self.crypto.decrypt()
        scores = []
        for i in range(8):
            df = pandas.read_csv(f"data/group{i+1}.csv")
            df["score"] = df["score"].astype("float64")
            scores.append(sum(df["score"].tolist()))
        return scores

    def data_sum(self):
        scores = self._visual_sum_pre_do()
        df = pandas.DataFrame(columns=["组号", "总分"])
        df.iloc[:, 0] = [i + 1 for i in range(8)]
        df.iloc[:, 1] = scores
        print(df.sort_values(by="总分", ascending=False))
        return df.sort_values(by="总分", ascending=False)

    def data_each_group(self):
        self.crypto.decrypt()
        scores = []
        for i in range(8):
            df = pandas.read_csv(f"data/group{i+1}.csv")
            df["score"] = df["score"].astype("float64")
            scores.append(sorted(df["score"].tolist(), reverse=True))
        return scores

    def main_visual(self):
        df_sum = self.data_sum()
        # df_each_group = self.data_each_group()
        plt.bar(df_sum["组号"], df_sum["总分"])
        plt.title("总分排名")
        plt.xlabel("组号")
        plt.ylabel("总分")
        plt.show()


class Main:
    def __init__(self):
        self.crypto = Crypto()
        self.fern = Fernet(self.crypto.load_key_file())
        self.rwcsv = RwCsv()
        self.visual = Visual()

    def run(self):
        if not os.path.exists("crypto/passwd/passwd.txt"):
            self._create_passwd_file()
        else:
            oper = input(
                "请输入操作(1.输入密码并复制密钥以进行加分操作 2.修改密码 3.绘制图表 4.退出 5.补救):"
            )
            if oper == "1":
                self._check_passwd()
            elif oper == "2":
                self._change_passwd()
            elif oper == "3":
                self.visual.main_visual()
            elif oper == "4":
                sys.exit()
            elif oper == "5":
                self.crypto.create_key_file()
                self.crypto.encrypt()
            else:
                print("输入错误")

    def _create_passwd_file(self):
        passwd = getpass.getpass("请输入密码:")
        passwd = hashlib.sha512(passwd.encode()).hexdigest()
        with open("crypto/passwd/passwd.txt", "w") as f:
            f.write(passwd)

    def _load_passwd_file(self):
        with open("crypto/passwd/passwd.txt", "r") as f:
            passwd = f.read()
        return passwd

    def _check_passwd(self):
        passwd = getpass.getpass("请输入密码:")
        passwd = hashlib.sha512(passwd.encode()).hexdigest()
        if passwd == self._load_passwd_file():
            self.operation()
        else:
            print("密码错误")

    def _change_passwd(self):
        old_passwd = getpass.getpass("请输入旧密码:")
        old_passwd = hashlib.sha512(old_passwd.encode()).hexdigest()
        if old_passwd == self._load_passwd_file():
            new_passwd = getpass.getpass("请输入新密码:")
            new_passwd = hashlib.sha512(new_passwd.encode()).hexdigest()
            with open("crypto/passwd/passwd.txt", "w") as f:
                f.write(new_passwd)
            print("密码修改成功")
        else:
            print("密码错误")

    def operation(self):
        self.crypto.decrypt()
        while True:
            oper = input("请输入操作(1.加分 2.退出):")
            if oper == "1":
                while True:
                    name = input("请输入姓名或分数，如果是第一次输入，请先输入数字:")
                    if name == "exit":
                        break
                    self.rwcsv.change(name)
            elif oper == "2":
                self.crypto.create_key_file()
                self.crypto.encrypt()
                break
            else:
                print("输入错误")


if __name__ == "__main__":
    try:
        pm = Main()
        pm.run()
    except Exception as e:
        print(e)
        input("按任意键退出...")